package com.gitee.kamismile.stoneComEx.common.exception.server;

import com.gitee.kamismile.stoneComEx.util.StringUtil;
import com.gitee.kamismile.stone.commmon.base.ResultVO;
import com.gitee.kamismile.stone.commmon.exception.BusinessException;
import com.gitee.kamismile.stone.commmon.util.ValueUtils;
import com.healthmarketscience.jackcess.ConstraintViolationException;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.i18n.LocaleContextResolver;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

@ControllerAdvice
public class SimpleFluxException {
    private static final Logger logger =  LoggerFactory.getLogger(SimpleFluxException.class);

    @Autowired
    private ReloadableResourceBundleMessageSource messageSource;


    @ExceptionHandler(Throwable.class)
    public ResponseEntity handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        ResultVO errorMsg = new ResultVO();

        int code = -1;
        Locale locale = LocaleContextHolder.getLocale();
        String defMessage = messageSource.getMessage(String.valueOf(code), null, locale);
        if (ex.getCause() instanceof InvocationTargetException) {
            ex = ex.getCause();
        }

        if (ex.getCause() instanceof BusinessException) {
            ex = ex.getCause();
        } else if (ex.getCause() instanceof DuplicateKeyException) {
            ex = ex.getCause();
        }
        if (ex instanceof BusinessException) {
            code = ((BusinessException) ex).getCode();
            defMessage = messageSource.getMessage(String.valueOf(code), ((BusinessException) ex).getArgs(), locale);
            if(defMessage.equals(String.valueOf(code))){
                defMessage = ValueUtils.isStringNull(((BusinessException) ex).getMessage());
            }

            errorMsg.setData(((BusinessException) ex).getData());
        }else if (ex instanceof WebExchangeBindException){
            String message = ((WebExchangeBindException) ex).getFieldError().getDefaultMessage();
            defMessage=ValueUtils.isStringNull(message,defMessage);
            code=((WebExchangeBindException) ex).getStatusCode().value();
        }else if (ex instanceof ResponseStatusException) {
            String message = ((ResponseStatusException) ex).getReason();
            defMessage=ValueUtils.isStringNull(message,defMessage);
            code=((ResponseStatusException) ex).getStatusCode().value();
        } else if (ex instanceof IllegalArgumentException) {
            String message = ex.getMessage();
            defMessage=ValueUtils.isStringNull(message,defMessage);
        } else if (ex instanceof org.springframework.web.bind.MethodArgumentNotValidException) {
//            message = ((MethodArgumentNotValidException) ex).getBindingResult()
//                    .getAllErrors().stream()
//                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
//                    .findFirst().get();
            String message = ((MethodArgumentNotValidException) ex).getBindingResult()
                    .getFieldError().getDefaultMessage();
            defMessage=ValueUtils.isStringNull(message,defMessage);
        } else if (ex instanceof DuplicateKeyException) {
            String message = messageSource.getMessage("10001", null, locale);
            defMessage=ValueUtils.isStringNull(message,defMessage);
        }
        errorMsg.setCode(String.valueOf(code));
        errorMsg.setMessage(defMessage);
        logger.error(defMessage, ex);
        Map responseMap = new HashMap();
        responseMap.put("code", errorMsg.getCode());
        responseMap.put("data", errorMsg.getData());
        responseMap.put("message", errorMsg.getMessage());
        responseMap.put("errors", Arrays.asList(errorMsg));
        HttpStatus httpStatus = HttpStatus.resolve(code);
        httpStatus= Objects.isNull(httpStatus)?HttpStatus.OK:httpStatus;
        return new ResponseEntity<Map>(responseMap,httpStatus );
//        return Mono.just(errorMsg);
    }

}
